/*******************************************************************************
   @file    dev_Spi.c
   @author  H.M.Shim (elecage@gmail.com)
   @version 
   @date    2013. 7. 31.
   @brief   
  ******************************************************************************
  The MIT License (MIT)

Copyright (c) 2013 <copyright holders>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
  ******************************************************************************
  */



/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "usbstdio.h"
#include "devio.h"
#include "dev_gpio.h"
#include "dev_Spi.h"
#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_it.h"
#include "cmdline.h"
/* Private typedef -----------------------------------------------------------*/

/* Private define ------------------------------------------------------------*/
#define DEV_SPI1_DEVICE_NAME ((int8_t*)"spi1")	/**< @brief SPI 1번 포트 장치명 */
#define DEV_SPI2_DEVICE_NAME ((int8_t*)"spi2")	/**< @brief SPI 2번 포트 장치명 */
#define DEV_SPI3_DEVICE_NAME ((int8_t*)"spi3")	/**< @brief SPI 3번 포트 장치명 */
#define DEV_SPI4_DEVICE_NAME ((int8_t*)"spi4")	/**< @brief SPI 4번 포트 장치명 */
#define DEV_SPI5_DEVICE_NAME ((int8_t*)"spi5")	/**< @brief SPI 5번 포트 장치명 */
#define DEV_SPI6_DEVICE_NAME ((int8_t*)"spi6")	/**< @brief SPI 6번 포트 장치명 */
/* Private macro -------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/

SPI_InitTypeDef spi_initStructure;
Dev_Spi_flag devSpiFlag[NUM_SPI];

int8_t *devSpiName[NUM_SPI] = { DEV_SPI1_DEVICE_NAME,
		DEV_SPI2_DEVICE_NAME,
		DEV_SPI3_DEVICE_NAME };
SPI_TypeDef* SPI_Type[NUM_SPI] = { SPI1, SPI2, SPI3};
int32_t spiTimeout = 0x00;
/* Private function prototypes -----------------------------------------------*/
void spiTimeOut_UserCallback(void);
void spiDelay(uint32_t delay);
/* Private functions ---------------------------------------------------------*/
int32_t registerDev_Spi(void)
{
	int i;
	DeviceStructure devStructure;
	for (i = 0; i < NUM_SPI; i++) {
		devStructure.dd = Dev_SPI1 + i;
		devStructure.devname = devSpiName[i];
		devStructure.openFunc = dev_SpiOpen;
		devStructure.readFunc = dev_SpiRead;
		devStructure.writeFunc = dev_SpiWrite;
		devStructure.ioctlFunc = dev_SpiIoctl;
		devStructure.closeFunc = dev_SpiClose;
#ifdef USE_CMDLINE
		devStructure.openCmdFunc = dev_SpiOpenCmd;
		devStructure.readCmdFunc = dev_SpiReadCmd;
		devStructure.writeCmdFunc = dev_SpiWriteCmd;
		devStructure.ioctlCmdFunc = dev_SpiIoctlCmd;
		devStructure.closeCmdFunc = dev_SpiCloseCmd;
#endif /* USE_CMDLINE */

		devSpiFlag[i].stat = 0;

		registerDevice(devStructure);
	}

	return 0;
}

int32_t dev_SpiOpen(const int8_t* devname, int32_t flags)
{
	int32_t devNum;
	int16_t i;

	SPI_InitTypeDef SPI_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;

	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

	if (strcmp((const char*) devname, (const char*) DEV_SPI1_DEVICE_NAME)
				== 0) {
		devNum = 0;
	}else if (strcmp((const char*) devname, (const char*) DEV_SPI2_DEVICE_NAME)
			== 0) {
		devNum = 1;
	}else if (strcmp((const char*) devname, (const char*) DEV_SPI3_DEVICE_NAME)
			== 0) {
		devNum = 2;
	}


	if((flags & DEV_SPI_FLAG_2LINE_RXONLY) == DEV_SPI_FLAG_2LINE_RXONLY) {
		SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_RxOnly;
		devSpiFlag[devNum].direction  = SPI_Direction_2Lines_RxOnly;
	} else if((flags & DEV_SPI_FLAG_1LINE_TXONLY) == DEV_SPI_FLAG_1LINE_TXONLY) {
		SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
		devSpiFlag[devNum].direction  = SPI_Direction_1Line_Tx;
	} else if((flags & DEV_SPI_FLAG_1LINE_RXONLY) == DEV_SPI_FLAG_1LINE_RXONLY) {
		SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Rx;
		devSpiFlag[devNum].direction  = SPI_Direction_1Line_Rx;
	} else {	/** 기본은 양방향 */
		SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
		devSpiFlag[devNum].direction  = DEV_SPI_FLAG_2LINE_FULL;
	}

	if((flags & DEV_SPI_FLAG_DATA_16BIT) == DEV_SPI_FLAG_DATA_16BIT) {
		SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
		devSpiFlag[devNum].dataSize = 16;
	} else { /** 기본은 8바이트 */
		SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
		devSpiFlag[devNum].dataSize = 8;
	}
	if((flags & DEV_SPI_FLAG_POL_HIGH) == DEV_SPI_FLAG_POL_HIGH) {
		SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
		devSpiFlag[devNum].pol = SPI_CPOL_High;
	} else {
		SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
		devSpiFlag[devNum].pol = SPI_CPOL_Low;
	}
	if((flags & DEV_SPI_FLAG_PHASE_2) == DEV_SPI_FLAG_PHASE_2) {
		SPI_InitStructure.SPI_CPHA =  SPI_CPHA_2Edge;
		devSpiFlag[devNum].phase = SPI_CPHA_2Edge;
	} else {
		SPI_InitStructure.SPI_CPHA =  SPI_CPHA_1Edge;
		devSpiFlag[devNum].phase = SPI_CPHA_1Edge;
	}

	if((flags & DEV_SPI_FLAG_SLAVE) == DEV_SPI_FLAG_SLAVE) {
		SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
		devSpiFlag[devNum].ms = SPI_Mode_Slave;
		SPI_InitStructure.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set;
	} else {
		SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
		devSpiFlag[devNum].ms = SPI_Mode_Master;
		SPI_InitStructure.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set;
	}

	if((flags & DEV_SPI_FLAG_LSB) == DEV_SPI_FLAG_LSB) {
		SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB;
		devSpiFlag[devNum].firstbit = SPI_FirstBit_LSB;
	} else {
		SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
		devSpiFlag[devNum].firstbit = SPI_FirstBit_MSB;
	}

	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;

	switch(devNum) {
	case 0:
		RCC_AHB1PeriphClockCmd(SPI1_MISO_GPIO_CLK, ENABLE);
		RCC_AHB1PeriphClockCmd(SPI1_MOSI_GPIO_CLK, ENABLE);
		RCC_AHB1PeriphClockCmd(SPI1_SCK_GPIO_CLK, ENABLE);

		GPIO_InitStructure.GPIO_Pin = SPI1_MISO_PIN;
		GPIO_Init(SPI1_MISO_GPIO_PORT, &GPIO_InitStructure);
		GPIO_PinAFConfig(SPI1_MISO_GPIO_PORT, SPI1_MISO_SOURCE, GPIO_AF_SPI1);

		GPIO_InitStructure.GPIO_Pin = SPI1_MOSI_PIN;
		GPIO_Init(SPI1_MOSI_GPIO_PORT, &GPIO_InitStructure);
		GPIO_PinAFConfig(SPI1_MOSI_GPIO_PORT, SPI1_MOSI_SOURCE, GPIO_AF_SPI1);

		GPIO_InitStructure.GPIO_Pin = SPI1_SCK_PIN;
		GPIO_Init(SPI1_SCK_GPIO_PORT, &GPIO_InitStructure);
		GPIO_PinAFConfig(SPI1_SCK_GPIO_PORT, SPI1_SCK_SOURCE, GPIO_AF_SPI1);

		if((flags & DEV_SPI_FLAG_SLAVE) == DEV_SPI_FLAG_SLAVE) {
			RCC_AHB1PeriphClockCmd(SPI1_NSS_GPIO_CLK, ENABLE);
			GPIO_InitStructure.GPIO_Pin = SPI1_NSS_PIN;
			GPIO_Init(SPI1_NSS_GPIO_PORT, &GPIO_InitStructure);
			GPIO_PinAFConfig(SPI1_NSS_GPIO_PORT, SPI1_NSS_SOURCE, GPIO_AF_SPI1);
		}

		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
		GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

		GPIO_InitStructure.GPIO_Pin = SPI1_CS1_GPIO_PIN;
		GPIO_Init(SPI1_CS1_GPIO_PORT, &GPIO_InitStructure);

		GPIO_InitStructure.GPIO_Pin = SPI1_CS2_GPIO_PIN;
		GPIO_Init(SPI1_CS2_GPIO_PORT, &GPIO_InitStructure);

		GPIO_InitStructure.GPIO_Pin = SPI1_CS3_GPIO_PIN;
		GPIO_Init(SPI1_CS3_GPIO_PORT, &GPIO_InitStructure);

		GPIO_InitStructure.GPIO_Pin = SPI1_CS4_GPIO_PIN;
		GPIO_Init(SPI1_CS4_GPIO_PORT, &GPIO_InitStructure);

		devSpiFlag[devNum].csPort[0] = SPI1_CS1_GPIO_PORT;
		devSpiFlag[devNum].csPin[0]	 = SPI1_CS1_GPIO_PIN;

		devSpiFlag[devNum].csPort[1] = SPI1_CS2_GPIO_PORT;
		devSpiFlag[devNum].csPin[1]	 = SPI1_CS2_GPIO_PIN;

		devSpiFlag[devNum].csPort[2] = SPI1_CS3_GPIO_PORT;
		devSpiFlag[devNum].csPin[2]	 = SPI1_CS3_GPIO_PIN;

		devSpiFlag[devNum].csPort[3] = SPI1_CS4_GPIO_PORT;
		devSpiFlag[devNum].csPin[3]	 = SPI1_CS4_GPIO_PIN;

		RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
		break;
	case 1:
		devNum = 1;
		RCC_AHB1PeriphClockCmd(SPI2_MISO_GPIO_CLK, ENABLE);
		RCC_AHB1PeriphClockCmd(SPI2_MOSI_GPIO_CLK, ENABLE);
		RCC_AHB1PeriphClockCmd(SPI2_SCK_GPIO_CLK, ENABLE);

		GPIO_InitStructure.GPIO_Pin = SPI2_MISO_PIN;
		GPIO_Init(SPI2_MISO_GPIO_PORT, &GPIO_InitStructure);
		GPIO_PinAFConfig(SPI2_MISO_GPIO_PORT, SPI2_MISO_SOURCE, GPIO_AF_SPI2);

		GPIO_InitStructure.GPIO_Pin = SPI2_MOSI_PIN;
		GPIO_Init(SPI2_MOSI_GPIO_PORT, &GPIO_InitStructure);
		GPIO_PinAFConfig(SPI2_MOSI_GPIO_PORT, SPI2_MOSI_SOURCE, GPIO_AF_SPI2);

		GPIO_InitStructure.GPIO_Pin = SPI2_SCK_PIN;
		GPIO_Init(SPI2_SCK_GPIO_PORT, &GPIO_InitStructure);
		GPIO_PinAFConfig(SPI2_SCK_GPIO_PORT, SPI2_SCK_SOURCE, GPIO_AF_SPI2);

		if((flags & DEV_SPI_FLAG_SLAVE) == DEV_SPI_FLAG_SLAVE) {
			RCC_AHB1PeriphClockCmd(SPI2_NSS_GPIO_CLK, ENABLE);
			GPIO_InitStructure.GPIO_Pin = SPI2_NSS_PIN;
			GPIO_Init(SPI2_NSS_GPIO_PORT, &GPIO_InitStructure);
			GPIO_PinAFConfig(SPI2_NSS_GPIO_PORT, SPI2_NSS_SOURCE, GPIO_AF_SPI2);
		}

		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
		GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

		GPIO_InitStructure.GPIO_Pin = SPI2_CS1_GPIO_PIN;
		GPIO_Init(SPI2_CS1_GPIO_PORT, &GPIO_InitStructure);

		GPIO_InitStructure.GPIO_Pin = SPI2_CS2_GPIO_PIN;
		GPIO_Init(SPI2_CS2_GPIO_PORT, &GPIO_InitStructure);

		GPIO_InitStructure.GPIO_Pin = SPI2_CS3_GPIO_PIN;
		GPIO_Init(SPI2_CS3_GPIO_PORT, &GPIO_InitStructure);

		GPIO_InitStructure.GPIO_Pin = SPI2_CS4_GPIO_PIN;
		GPIO_Init(SPI2_CS4_GPIO_PORT, &GPIO_InitStructure);

		devSpiFlag[devNum].csPort[0] = SPI2_CS1_GPIO_PORT;
		devSpiFlag[devNum].csPin[0]	 = SPI2_CS1_GPIO_PIN;

		devSpiFlag[devNum].csPort[1] = SPI2_CS2_GPIO_PORT;
		devSpiFlag[devNum].csPin[1]	 = SPI2_CS2_GPIO_PIN;

		devSpiFlag[devNum].csPort[2] = SPI2_CS3_GPIO_PORT;
		devSpiFlag[devNum].csPin[2]	 = SPI2_CS3_GPIO_PIN;

		devSpiFlag[devNum].csPort[3] = SPI2_CS4_GPIO_PORT;
		devSpiFlag[devNum].csPin[3]	 = SPI2_CS4_GPIO_PIN;

		RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
		break;
	case 2:
		devNum = 2;
		RCC_AHB1PeriphClockCmd(SPI3_MISO_GPIO_CLK, ENABLE);
		RCC_AHB1PeriphClockCmd(SPI3_MOSI_GPIO_CLK, ENABLE);
		RCC_AHB1PeriphClockCmd(SPI3_SCK_GPIO_CLK, ENABLE);

		GPIO_InitStructure.GPIO_Pin = SPI3_MISO_PIN;
		GPIO_Init(SPI3_MISO_GPIO_PORT, &GPIO_InitStructure);
		GPIO_PinAFConfig(SPI3_MISO_GPIO_PORT, SPI3_MISO_SOURCE, GPIO_AF_SPI3);

		GPIO_InitStructure.GPIO_Pin = SPI3_MOSI_PIN;
		GPIO_Init(SPI3_MOSI_GPIO_PORT, &GPIO_InitStructure);
		GPIO_PinAFConfig(SPI3_MOSI_GPIO_PORT, SPI3_MOSI_SOURCE, GPIO_AF_SPI3);

		GPIO_InitStructure.GPIO_Pin = SPI3_SCK_PIN;
		GPIO_Init(SPI3_SCK_GPIO_PORT, &GPIO_InitStructure);
		GPIO_PinAFConfig(SPI3_SCK_GPIO_PORT, SPI3_SCK_SOURCE, GPIO_AF_SPI3);

		if((flags & DEV_SPI_FLAG_SLAVE) == DEV_SPI_FLAG_SLAVE) {
			RCC_AHB1PeriphClockCmd(SPI3_NSS_GPIO_CLK, ENABLE);
			GPIO_InitStructure.GPIO_Pin = SPI3_NSS_PIN;
			GPIO_Init(SPI3_NSS_GPIO_PORT, &GPIO_InitStructure);
			GPIO_PinAFConfig(SPI3_NSS_GPIO_PORT, SPI3_NSS_SOURCE, GPIO_AF_SPI3);
		}

		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
		GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

		GPIO_InitStructure.GPIO_Pin = SPI3_CS1_GPIO_PIN;
		GPIO_Init(SPI3_CS1_GPIO_PORT, &GPIO_InitStructure);

		GPIO_InitStructure.GPIO_Pin = SPI3_CS2_GPIO_PIN;
		GPIO_Init(SPI3_CS2_GPIO_PORT, &GPIO_InitStructure);

		GPIO_InitStructure.GPIO_Pin = SPI3_CS3_GPIO_PIN;
		GPIO_Init(SPI3_CS3_GPIO_PORT, &GPIO_InitStructure);

		GPIO_InitStructure.GPIO_Pin = SPI3_CS4_GPIO_PIN;
		GPIO_Init(SPI3_CS4_GPIO_PORT, &GPIO_InitStructure);

		devSpiFlag[devNum].csPort[0] = SPI3_CS1_GPIO_PORT;
		devSpiFlag[devNum].csPin[0]	 = SPI3_CS1_GPIO_PIN;

		devSpiFlag[devNum].csPort[1] = SPI3_CS2_GPIO_PORT;
		devSpiFlag[devNum].csPin[1]	 = SPI3_CS2_GPIO_PIN;

		devSpiFlag[devNum].csPort[2] = SPI3_CS3_GPIO_PORT;
		devSpiFlag[devNum].csPin[2]	 = SPI3_CS3_GPIO_PIN;

		devSpiFlag[devNum].csPort[3] = SPI3_CS4_GPIO_PORT;
		devSpiFlag[devNum].csPin[3]	 = SPI3_CS4_GPIO_PIN;
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
	}

	for(i = 0 ; i < NUM_SLAVE ; i++)  {
		GPIO_SetBits(devSpiFlag[devNum].csPort[i], devSpiFlag[devNum].csPin[i]);
	}
	devSpiFlag[devNum].currentCs = 0;
	SPI_Init(SPI_Type[devNum], &SPI_InitStructure);
	devSpiFlag[devNum].SPI_InitStructure = SPI_InitStructure;
	SPI_Cmd(SPI_Type[devNum], ENABLE);

	devSpiFlag[devNum].timeout = ((uint32_t) 0xff);
	devSpiFlag[devNum].stat |= DEV_STAT_OPEN;

	return Dev_SPI1 + devNum; /**< Device Descriptor를 리턴 */
}

ssize_t dev_SpiWrite(int32_t dd, const void *buf, size_t n)
{
	size_t i = 0;
	uint16_t* data16bit;
	uint8_t* data;
	int32_t devNum = dd - Dev_SPI1;

	if(devSpiFlag[devNum].dataSize == 16) {
		 data16bit = (uint16_t*)buf;
	} else {
		 data = (uint8_t*) buf;
	}
	if ((devSpiFlag[devNum].stat & DEV_STAT_OPEN) == 0) {
		return DEV_ERR_NOT_OPEN;
	}
	GPIO_ResetBits(devSpiFlag[devNum].csPort[devSpiFlag[devNum].currentCs],
			       devSpiFlag[devNum].csPin[devSpiFlag[devNum].currentCs]);

	//spiDelay(devSpiFlag[devNum].timeout);

	for(i = 0 ; i < n ; i++) {
		if(devSpiFlag[devNum].dataSize == 16) {
			data16bit = (uint16_t*)data;
			SPI_SendData(SPI_Type[devNum], *data16bit);
			*data16bit = SPI_ReceiveData(SPI_Type[devNum]);
			data16bit++;
		} else {
			SPI_SendData(SPI_Type[devNum], *data);
			*data = SPI_ReceiveData(SPI_Type[devNum]);
			data++;
		}
		while(SPI_I2S_GetFlagStatus(SPI_Type[devNum], SPI_I2S_FLAG_BSY) == SET);

	}
	GPIO_SetBits(devSpiFlag[devNum].csPort[devSpiFlag[devNum].currentCs],
			       devSpiFlag[devNum].csPin[devSpiFlag[devNum].currentCs]);
	//spiDelay(devSpiFlag[devNum].timeout);
	return i;
}

ssize_t	dev_SpiRead(int32_t dd, void *buf, size_t nbytes)
{
	size_t i = 0;
	uint8_t* data8bit = (uint8_t*) buf;
	uint16_t* data16bit = (uint16_t*) buf;

	int32_t devNum = dd - Dev_SPI1;

	if ((devSpiFlag[devNum].stat & DEV_STAT_OPEN) == 0) {
		return DEV_ERR_NOT_OPEN;
	}
	GPIO_ResetBits(devSpiFlag[devNum].csPort[devSpiFlag[devNum].currentCs],
			       devSpiFlag[devNum].csPin[devSpiFlag[devNum].currentCs]);

	//spiDelay(devSpiFlag[devNum].timeout);

	for(i = 0 ; i < nbytes ; i++) {
		if(devSpiFlag[devNum].dataSize == 16) {
			SPI_SendData(SPI_Type[devNum], 0);
			while(SPI_I2S_GetFlagStatus(SPI_Type[devNum], SPI_I2S_FLAG_BSY) == SET);
			*data16bit = SPI_ReceiveData(SPI_Type[devNum]);
			data16bit++;
		} else {
			SPI_SendData(SPI_Type[devNum], 0);
			while(SPI_I2S_GetFlagStatus(SPI_Type[devNum], SPI_I2S_FLAG_BSY) == SET);
			*data8bit = SPI_ReceiveData(SPI_Type[devNum]);
			data8bit++;
		}
	}
	GPIO_SetBits(devSpiFlag[devNum].csPort[devSpiFlag[devNum].currentCs],
				       devSpiFlag[devNum].csPin[devSpiFlag[devNum].currentCs]);
	return i;
}
ssize_t dev_SpiIoctl(int32_t dd, int32_t request, void* data)
{
	int32_t devNum = dd - Dev_SPI1;
	int8_t datasize;
	if ((devSpiFlag[devNum].stat & DEV_STAT_OPEN) == 0) {
		return DEV_ERR_NOT_OPEN;
	}
	switch(request) {
	case DEV_SPI_SET_DATASIZE:
		datasize = *(int8_t*)data;
		if(datasize == 16) {
			devSpiFlag[devNum].dataSize = 16;
			devSpiFlag[devNum].SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
		} else {
			devSpiFlag[devNum].dataSize = 8;
			devSpiFlag[devNum].SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
		}
		SPI_Init(SPI_Type[devNum], &devSpiFlag[devNum].SPI_InitStructure);
	}
	return 0;
}
int32_t dev_SpiClose(int32_t dd)
{
	return 0;
}

void dev_SpiConfigInt(uint8_t portsource, EXTI_Config* config)
{

}

#ifdef USE_CMDLINE

int32_t dev_SpiOpenCmd(int32_t argc, int8_t *argv[])
{
	int32_t flags = 0;
	int32_t k = 0;

	if(argc < 3)
		return CMDLINE_TOO_FEW_ARGS;
	DeviceStructure* device = deviceTable;

	while(device->devname != 0) {
		if(strcmp((char*)device->devname, (char*)argv[1]) == 0) {

			for(k = 2 ; k < argc ; k++) {

				if(strcmp((char*)argv[k], "readonly")  == 0) {
					flags |= DEV_RDONLY;
				}
				if(strcmp((char*)argv[k], "writeonly") == 0) {
					flags |= DEV_WRONLY;
				}
				if(strcmp((char*)argv[k], "readwrite") == 0) {
					flags |= DEV_RDWR;
				}
				if(strcmp((char*)argv[k], DEV_ARG_SPI_SET_SLAVE) == 0) {
					flags |= DEV_SPI_FLAG_SLAVE;
				}
				if(strcmp((char*)argv[k], DEV_ARG_SPI_SET_POL_HIGH) == 0) {
					flags |= DEV_SPI_FLAG_POL_HIGH;
				}
				if(strcmp((char*)argv[k], DEV_ARG_SPI_SET_PHA_2) == 0) {
					flags |= DEV_SPI_FLAG_PHASE_2;
				}
				if(strcmp((char*)argv[k], DEV_ARG_SPI_DATA_16BIT) ==  0) {
					flags |= DEV_SPI_FLAG_DATA_16BIT;
				}
			}

			dev_SpiOpen(device->devname, flags);
			return 0;
		}
		device++;
	}
	return CMDLINE_INVALID_ARGS;
}
int32_t dev_SpiReadCmd(int32_t argc, int8_t *argv[])
{
	if(argc < 4)
		return CMDLINE_TOO_FEW_ARGS;
	if(argc > 11)
		return CMDLINE_TOO_MANY_ARGS;

	uint8_t data8[8];
	uint16_t data16[8];
	uint16_t numData =(uint16_t)atoi((char*)argv[3]);
	uint16_t i;

	DeviceStructure* device = deviceTable;
	while(device->devname != 0) {
		if(strcmp((char*)device->devname, (char*)argv[1]) == 0) {


			if(strcmp((char*)argv[2], "16bit")==0) {
				dev_SpiRead(device->dd, &data16, numData);
				for(i = 0 ; i < numData ; i++)
					usbPrintf((int8_t*)"read %s : %4x\n", argv[1], data16[i]);
			} else if(strcmp((char*)argv[2], "8bit")==0) {
				dev_SpiRead(device->dd, &data8, numData);
				for(i = 0 ; i < numData ; i++)
					usbPrintf((int8_t*)"read %s : %4x\n", argv[1], data8[i]);
			}
			return 0;
		}
		device++;
	}
	return CMDLINE_INVALID_ARGS;
}
int32_t dev_SpiWriteCmd(int32_t argc, int8_t *argv[])
{
	return 0;
}
int32_t dev_SpiIoctlCmd(int32_t argc, int8_t *argv[])
{
	return 0;
}
int32_t dev_SpiCloseCmd(int32_t argc, int8_t *argv[])
{
	if(argc < 3)
		return CMDLINE_TOO_FEW_ARGS;
	DeviceStructure* device = deviceTable;

	while(device->devname != 0) {
		if(strcmp((char*)device->devname, (char*)argv[1]) == 0) {
			return dev_SpiClose(device->dd);
		}
		device++;
	}
	return CMDLINE_INVALID_ARGS;
}
#endif /* USE_CMDLINE */

void spiTimeOut_UserCallback(void)
{

}

void spiDelay(uint32_t delay)
{
	while(delay--);
}
